﻿using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using System.Data.SqlClient;
using System.Linq.Expressions;
using Wenyu.Framework.IBusinessServices;

namespace Wenyu.Framework.BusinessServices
{
    public abstract class  BaseService: IBaseService
    {
        protected DbContext Context { get; set; }
        /// <summary>
        /// 构造函数注入
        /// </summary>
        /// <param name="context"></param>
        public BaseService(DbContext context)
        {
            Context=context;
        }

        #region Query 查询
        public IQueryable<T> Set<T>() where T : class
        {
            return this.Context.Set<T>();
        }

        public T Find<T>(int id) where T : class
        {
            return this.Context.Set<T>().Find(id);
        }

        public IQueryable<T> Query<T>(Expression<Func<T, bool>> funcWhere) where T : class
        {
            return this.Context.Set<T>().Where<T>(funcWhere);
        }

        public PagingData<T> QueryPage<T, S>(Expression<Func<T, bool>> funcWhere, int pageSize, int pageIndex, Expression<Func<T, S>> funcOrderBy, bool isAsc = true) where T : class
        {
            var list=Set<T>();
            if (funcWhere != null)
            {
                list=list.Where(funcWhere);
            }
            if (isAsc)
            {
                list = list.OrderBy(funcOrderBy);
            }
            else
            {
                list = list.OrderByDescending(funcOrderBy);
            }
            PagingData<T> result = new PagingData<T>()
            {
                DataList = list.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(),
                RecordCount = list.Count(),
                PageIndex=pageIndex,
                PageSize=pageSize,
            };
            return result;

        }

        

        

        #endregion

        #region Insert 添加

        public T Insert<T>(T t) where T : class
        {
            this.Context.Set<T>().Add(t);
            this.Commit();
            return t;
        }

        public IEnumerable<T> Insert<T>(IEnumerable<T> tList) where T : class
        {
            this.Context.Set<T>().AddRange(tList);
            this.Commit();
            return tList;
        }

        #endregion

        #region Update 修改

        public int Update<T>(T t) where T : class
        {
            this.Context.Set<T>().Attach(t);
            this.Context.Entry<T>(t).State = EntityState.Modified;
            return this.Commit();
        }

        public int Update<T>(IEnumerable<T> tList) where T : class
        {
            foreach (var t in tList)
            {
                this.Context.Set<T>().Attach(t);
                this.Context.Entry<T>(t).State=EntityState.Modified;
            }
            return this.Commit ();
        }

        #endregion

        #region Delete 删除
        public int Delete<T>(T t) where T : class
        {
            if (t == null) throw new ArgumentNullException("this is null");
            this.Context.Set<T>().Attach(t);
            this.Context.Set<T>().Remove(t);
            return this.Commit();
        }

        public int Delete<T>(int id) where T : class
        {
            T t=this.Find<T>(id);
            if (t == null) throw new ArgumentNullException("this is null");
            this.Context.Set<T>().Remove(t);
            return this.Commit();
        }

        public int Delete<T>(IEnumerable<T> tList) where T : class
        {
            foreach(var t in tList)
            {
                this.Context.Set<T>().Attach(t);
            }
            
            this.Context.Set<T>().RemoveRange(tList);
            return this.Commit();
        }

        #endregion


        #region Other
        public void Excute<T>(string sql, SqlParameter[] parameters) where T : class
        {
            IDbContextTransaction transaction = null;
            try
            {
                transaction = this.Context.Database.BeginTransaction();
                this.Context.Database.ExecuteSqlRaw(sql, parameters);
                transaction.Commit();
            }catch (Exception ex)
            {
                if(transaction != null)
                    transaction.Rollback();
                throw;
            }

        }

        public IQueryable<T> ExcuteQuery<T>(string sql, SqlParameter[] parameters) where T : class
        {
            return this.Context.Set<T>().FromSqlRaw(sql, parameters);
        }

        
        #endregion

        protected int Commit()
        {
            return this.Context.SaveChanges();
        }
        #region 伪代码

        #endregion

        public virtual void Dispose()
        {
            if(this.Context != null)
            {
                this.Context.Dispose();
            }
        }

    }
}